using System;
using FamilyTreeProject.GEDCOM.Common;
using System.Text.RegularExpressions;
using FamilyTreeProject.GEDCOM.Records;
using System.Globalization;

namespace FamilyTreeProject.GEDCOM
{
    /// <summary>
    /// This Class provides utilities for working with GEDCOM 5.5 data
    /// </summary>
    public class GEDCOMUtil
    {

        public static readonly Regex GEDCOMRegex = new Regex(@"(?<level>\d+)\s+(?<tag>[\S]+)(\s+(?<data>.+))?");

        public static string FamilyEventTags = "ANUL, DIV, DIVF, ENGA, MARR, MARB, MARC, MARL, MARS, EVEN";
        public static string FamilyLinkTags = "FAMC, FAMS";
        public static string IndividualEventTags = "ADOP, BAPM, BARM, BASM, BIRT, BLES, BURI, CENS, CHR, CHRA, CONF, CREM, DEAT, EMIG, FCOM, GRAD, IMMI, NATU, ORDN, PROB, RETI, WILL, EVEN";
        public static string IndividualAttributeTags = "CAST, DSCR, EDUC, IDNO, NATI, NCHI, NMR, OCCU, PROP, RELI, RESI, SSN, TITL";


        public static EventClass GetEventClass(string tag)
        {
            EventClass eventClass = EventClass.Unknown;

            if (FamilyEventTags.Trim().Contains(tag))
                eventClass = EventClass.Family;
            else if (IndividualEventTags.Trim().Contains(tag))
                eventClass = EventClass.Individual;
            else if (IndividualAttributeTags.Trim().Contains(tag))
                eventClass = EventClass.Attribute;

            return eventClass;
        }

        public static GEDCOMTag GetTag(string tag)
        {
            GEDCOMTag tagName;
            try
            {
                tagName = (GEDCOMTag)Enum.Parse(typeof(GEDCOMTag), tag);
            }
            catch (Exception c)
            {
                tagName = GEDCOMTag.UNKNOWN;
            }
            return tagName;
        }

        public static bool ParseGEDCOM(string text, GEDCOMRecord record)
        {
            try
            {
                // Init values.
                record.Clear();

                // Some GEDCOM files indent each record with whitespace, delete any
                // whitespace from the beginning and end of the record.
                text = text.Trim();

                // Return right away as nothing to parse.
                if (string.IsNullOrEmpty(text))
                    return false;

                // Get the parts of the record.
                Match match = GEDCOMRegex.Match(text);
                record.Level = Convert.ToInt32(match.Groups["level"].Value, CultureInfo.InvariantCulture);
                record.Tag = match.Groups["tag"].Value.Trim();
                record.Data = match.Groups["data"].Value.Trim();

                // For records the Id is specified in the tag, and the tag in the data
                if (record.Tag[0] == '@')
                {
                    record.Id = record.Tag;
                    record.Tag = record.Data;
                    record.Data = String.Empty;

                    // Some GEDCOM files have additional info, 
                    // we only handle the tag info.
                    int pos = record.Tag.IndexOf(' ');
                    if (pos != -1)
                        record.Tag = record.Tag.Substring(0, pos);
                }

                // If there are cross-reference Pointers they are defined in the Data
                if (!String.IsNullOrEmpty(record.Data) && record.Data[0] == '@')
                {
                    record.XRefId = record.Data;
                    record.Data = String.Empty;
                }

                return true;
            }
            catch
            {
                // This record is invalid, clear all values.
                record.Clear();
                return false;
            }
        }

    }
}
